package com.start.cloud.robotcore.properties;

import com.start.cloud.robotcore.Constants;
import com.start.cloud.robotcore.utils.StringUtil;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.mock.env.MockEnvironment;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by xxu on 2018/4/23.
 */
public class RobotClientConfiguration {
    private static RobotClientConfiguration INSTANCE = new RobotClientConfiguration();

    private RobotClientLocalProperties localProperies;

    private CompositePropertySource compositeProperty;

    private RobotClientConfiguration(){
        localProperies = new RobotClientLocalProperties();
        localProperies.load();
        compositeProperty = new CompositePropertySource(localProperies.getAppName() + "Configuration");
        ConfigurableEnvironment env = new MockEnvironment();
        RobotSpringCloudConfigSourceLocator locator = new RobotSpringCloudConfigSourceLocator(localProperies, env);
        List<PropertySource<?>> propertySources = new ArrayList<PropertySource<?>>();
        Map<String, Object> localProperties = new HashMap<String, Object>();
        for (Object key : localProperies.keySet()) {
            localProperties.put((String) key, localProperies.get(key));
        }
        MapPropertySource localSource = new MapPropertySource(RobotClientLocalProperties.DEFAULT_BEECONFIG_NAME + "Local", localProperties);
        propertySources.add(localSource);
        PropertySource<?> beeSource = locator.locate(RobotClientLocalProperties.DEFAULT_BEECONFIG_NAME);
        String evn = null;
        if (beeSource != null) {
            propertySources.add(beeSource);
            evn = (String) beeSource.getProperty(Constants.CONFIG_EVN_KEY);
        }
        localProperies.setEvn(evn);
        PropertySource<?> appPreSource = locator.locate(localProperies.getAppName() + "-pre");
        if (appPreSource != null) {
            propertySources.add(appPreSource);
        }
        PropertySource<?> appSource = locator.locate(localProperies.getAppName());
        if (appSource != null) {
            propertySources.add(appSource);
        }
        if (!StringUtil.isBlank(localProperies.getHostIndex())) {
            PropertySource<?> hostIndexSource = locator.locate(localProperies.getAppName() + "-" + localProperies.getHostIndex());
            if (hostIndexSource != null) {
                propertySources.add(hostIndexSource);
            }
        }
        for (PropertySource<?> source : propertySources) {
            if (source instanceof CompositePropertySource) {
                CompositePropertySource targetSource = (CompositePropertySource) source;
                for (PropertySource<?> ps : targetSource.getPropertySources()) {
                    compositeProperty.addFirstPropertySource(ps);
                }
            } else {
                compositeProperty.addFirstPropertySource(source);
            }
        }
        // 是否集中管理了应用端口号
//        String no = (String) compositeProperty.getProperty("bee.appdef-" + localProperies.getAppName() + ".no");
//        String p1 = (String) compositeProperty.getProperty("bee.appdef-" + localProperies.getAppName() + ".configClientPort");
//        String p2 = (String) compositeProperty.getProperty("bee.appdef-" + localProperies.getAppName() + ".tubePort");
//        if (StringUtil.isBlank(no) || StringUtil.isBlank(p1) || StringUtil.isBlank(p2)) {
//            throw new ApplicationNotDefException(localProperies.getAppName());
//        }
        // 为避免重要配置被重写，最后强制设定一个必须不能更改的property source
        Map<String, Object> mapSource = new HashMap<String, Object>();
//        if (!StringUtil.isBlank(p1)) {
//            mapSource.put(Constants.CONFIG_CLIENT_PORT, Integer.parseInt(p1));
//        }
//        if (!StringUtil.isBlank(p2)) {
//            mapSource.put(Constants.TUBE_PORT_KEY, Integer.parseInt(p2));
//        }
        MapPropertySource defaultSource = new MapPropertySource(RobotClientLocalProperties.DEFAULT_BEECONFIG_NAME + "Default", mapSource);
        mapSource.put(Constants.CONFIG_APPNAME_KEY, localProperies.getAppName());
        if (evn != null) {
            mapSource.put(Constants.CONFIG_EVN_KEY, evn);
        } else {
            mapSource.put(Constants.CONFIG_EVN_KEY, localProperies.getEvn());
        }
        compositeProperty.addFirstPropertySource(defaultSource);
    }

    public static RobotClientConfiguration get(){
        return INSTANCE;
    }

    public static RobotClientConfiguration reload() {
        INSTANCE = new RobotClientConfiguration();
        return get();
    }

    public RobotClientLocalProperties getLocalProperies() {
        return localProperies;
    }

    public CompositePropertySource getCompositeProperty() {
        return compositeProperty;
    }
}
